home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
dskut
/
exehex.zip
/
EXEHEX.C
next >
Wrap
C/C++ Source or Header
|
1991-03-30
|
13KB
|
509 lines
/************************************************************************
* exehex.c - This program converts Microsoft .EXE files to Intel *
* HEX files suitable for burning into EPROM. Like the *
* loader in MSDOS, exehex performs any necessary *
* relocation of segments in the .EXE file. *
************************************************************************/
/************************************************************************
* Copyright 1991, Charles F. Harris, C.F. Harris - Consulting. *
* *
* You may use this program for any purpose Commercial or Private with *
* following exceptions: *
* *
* 1) You may not sell this program without my written permission. *
* 2) You must leave this header comment unmodified, and intact. *
* 3) You must clearly identify any modifications that you make. *
* *
* This program is provided without any warantees or support, and is *
* to be used at your own risk. *
************************************************************************/
/************************************************************************
* This program was designed to run on 80x86 type machines, and to be *
* compiled with TURBO C++ V1.00. (that is not to say that it is *
* written in C++) *
* I can be reached at: chuck@eng.umd.edu *
* or at: Chuck Harris *
* C.F. Harris - Consulting *
* 9308 Canterbury Riding *
* Laurel, Maryland 20723 *
************************************************************************/
#include <dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <io.h>
#define ERR(s, c) if(opterr){\
char errbuf[2];\
errbuf[0] = c; errbuf[1] = '\n';\
(void) write(2, argv[0], (unsigned)strlen(argv[0]));\
(void) write(2, s, (unsigned)strlen(s));\
(void) write(2, errbuf, 2);}
#define DATAREC 0
#define EXADDR 2
#define ENDREC 1
struct EXEHDR {
unsigned signature; /* linker signature */
unsigned image_rsize; /* length of image mod 512 */
unsigned file_nblks; /* number of 512 byte blocks in file */
unsigned num_rels; /* number of relocation items */
unsigned header_size; /* size in paragraphs */
unsigned minheap_size; /* min num paragraphs in heap */
unsigned maxheap_size; /* max num paragraphs in heap */
unsigned stackseg_offset; /* offset of stack seg in load module */
unsigned initial_SP; /* initial value of stack register */
unsigned checksum; /* neg sum of all words in file */
unsigned initial_IP; /* initial value of instruction ptr */
unsigned codeseg_offset; /* offset of code seg in load module */
unsigned reltbl_offset; /* offset of first relocation item */
unsigned overlay_num; /* overlay number (0 == resident part) */
} exehdr;
typedef struct RELTBL {
unsigned rel_offset;
unsigned rel_segment;
} RELTBL;
int opterr = 1;
int optind = 1;
int optopt;
char *optarg;
char *tempfile = "exehexXXXXXX"; /* template for mktemp() */
char *tmpfname = 0; /* name of temp file */
FILE *fopen(),*fpi,*fpo,*fpt;
int ABORT(char *reason, ...);
unsigned char intelstring[100];
unsigned segment = 0, offset = 0;
unsigned imagelen = 0;
unsigned debug = 0;
unsigned no_end_record = 0;
RELTBL *reloc_tbl;
main(argc,argv)
int argc;
char **argv;
{
discover_options(argc,argv);
open_files(argc,argv);
read_exe_header();
read_relocation_table();
copy_image_to_temp();
relocate_image();
write_hex_file();
remove_temp_file();
}
discover_options(argc,argv)
int argc;
char **argv;
{
char *ourargs = "o:O:s:S:dDN?Hh";
int opt;
while((opt=getopt(argc,argv,ourargs)) != EOF){
switch(opt){
case 'd':
case 'D':
fprintf(stderr,"DEBUG level is: %d\n",++debug);
break;
case 's':
case 'S':
sscanf(optarg,"%x",&segment);
if(debug>=1){
fprintf(stderr,"Segment= 0x%X\n",segment);
}
break;
case 'o':
case 'O':
sscanf(optarg,"%x",&offset);
if(debug>=1){
fprintf(stderr,"Offset= 0x%X\n",offset);
}
break;
case 'N':
no_end_record++;
if(debug>=1){
fprintf(stderr,"No End Record\n");
}
break;
case '?':
case 'h':
case 'H':
how_to_use_message();
break;
default:
ABORT("Unknown argument");
}
}
}
/*
* getopt a wonderful little function that handles the command line.
* available courtesy of AT&T.
*/
int
getopt(argc, argv, opts)
int argc;
char **argv, *opts;
{
static int sp = 1;
register int c;
register char *cp;
if(sp == 1)
if(optind >= argc ||
argv[optind][0] != '-' || argv[optind][1] == '\0')
return(EOF);
else if(strcmp(argv[optind], "--") == NULL) {
optind++;
return(EOF);
}
optopt = c = argv[optind][sp];
if(c == ':' || (cp=strchr(opts, c)) == NULL) {
ERR(": illegal option -- ", c);
if(argv[optind][++sp] == '\0') {
optind++;
sp = 1;
}
return('?');
}
if(*++cp == ':') {
if(argv[optind][sp+1] != '\0')
optarg = &argv[optind++][sp+1];
else if(++optind >= argc) {
ERR(": option requires an argument -- ", c);
sp = 1;
return('?');
} else
optarg = argv[optind++];
sp = 1;
} else {
if(argv[optind][++sp] == '\0') {
sp = 1;
optind++;
}
optarg = NULL;
}
return(c);
}
open_files(argc,argv)
int argc;
char **argv;
{
int argind, files_found;
argc--,argv++; /* skip the program name */
for(argind=0,files_found=0; argind<argc; argind++){
if(argv[argind][0] == '-') continue;
if(debug>=1){
fprintf(stderr,"Argument is: %s\n",argv[argind]);
}
files_found++;
if(files_found==1 && !(fpi=fopen(argv[argind],"rb"))){
ABORT("opening %s",argv[argind]);
}
else if(files_found==2 && !(fpo=fopen(argv[argind],"wb"))){
ABORT("opening %s",argv[argind]);
}
else if(files_found > 2){
ABORT("too many file arguments\n");
}
}
if(files_found == 0){
ABORT("need a file to work on!");
}
else if(files_found == 1){
fpo = stdout;
}
tmpfname = mktemp(tempfile);
if(!(fpt=fopen(tmpfname,"wb+"))){
ABORT("can't open temporary file: %s",tmpfname);
}
}
read_exe_header()
{
if(fread(&exehdr,sizeof(struct EXEHDR),1,fpi) != 1){
ABORT("couldn't read exe header");
}
if(debug>=1){
print_exe_header();
}
if(exehdr.signature != 0x5a4d){
ABORT("bad exe signature:[0x%X]",exehdr.signature);
}
imagelen = exehdr.file_nblks*512 - exehdr.header_size*16;
imagelen -= (exehdr.image_rsize == 4) ? 0 : exehdr.image_rsize;
if(debug>=1){
fprintf(stderr,"binary image length is: 0x%X,(%dd)\n",imagelen,imagelen);
}
}
print_exe_header()
{
fprintf(stderr,"EXE HEADER:\n");
fprintf(stderr,"->signature = 0x%X\n",exehdr.signature);
fprintf(stderr,"->image_rsize = 0x%X\n",exehdr.image_rsize);
fprintf(stderr,"->file_nblks = 0x%X\n",exehdr.file_nblks);
fprintf(stderr,"->num_rels = 0x%X\n",exehdr.num_rels);
fprintf(stderr,"->header_size = 0x%X\n",exehdr.header_size);
fprintf(stderr,"->minheap_size = 0x%X\n",exehdr.minheap_size);
fprintf(stderr,"->maxheap_size = 0x%X\n",exehdr.maxheap_size);
fprintf(stderr,"->stackseg_offset = 0x%X\n",exehdr.stackseg_offset);
fprintf(stderr,"->initial_SP = 0x%X\n",exehdr.initial_SP);
fprintf(stderr,"->checksum = 0x%X\n",exehdr.checksum);
fprintf(stderr,"->initial_IP = 0x%X\n",exehdr.initial_IP);
fprintf(stderr,"->codeseg_offset = 0x%X\n",exehdr.codeseg_offset);
fprintf(stderr,"->reltbl_offset = 0x%X\n",exehdr.reltbl_offset);
fprintf(stderr,"->overlay_num = 0x%X\n",exehdr.overlay_num);
}
read_relocation_table()
{
int i;
if(exehdr.num_rels == 0) return; /* can't do much here */
reloc_tbl = (RELTBL *)malloc(exehdr.num_rels * sizeof(RELTBL));
if(!reloc_tbl){
ABORT("can't malloc reloc_tbl");
}
if(fseek(fpi,(long)exehdr.reltbl_offset,SEEK_SET) != 0){
ABORT("couldn't fseek to relocation tbl");
}
if(fread(reloc_tbl, sizeof(RELTBL) * exehdr.num_rels, 1, fpi) != 1){
ABORT("couldn't read relocation table");
}
if(debug>=1){
fprintf(stderr,"REL